#include "face_eigen_face_recognizer.h"

Face_Eigen_Face_Recognizer::Face_Eigen_Face_Recognizer(QWidget *parent)
    : CommonGraphicsView{parent}
{
    this->setWindowTitle("特征脸识别器");
    QPushButton * btn = new QPushButton(this);
    btn->setText("读取数据");
    connect(btn,&QPushButton::clicked,[=](){
        QString srcDirPath = QFileDialog::getExistingDirectory(
                    this, "choose src Directory",
                    "/Users/yangwei/Documents/tony/opencv/orl_faces");
        if (srcDirPath.isEmpty())
        {
            return;
        }
        else
        {
//            string filename = string("/Users/yangwei/Documents/tony/opencv/orl_faces/targetData.txt");
            string filename = string("/Users/yangwei/Documents/tony/opencv/myfaces/targetData.txt");
            out.open(filename,ios::out);
            qDebug() << "srcDirPath=" << srcDirPath;
            srcDirPath += "/";
            prepareImageData(srcDirPath.toStdString().c_str(),"");
            out.close();
        }

    });




    QPushButton *btnShow = new QPushButton(this);
    btnShow->move(0,btn->y()+btn->height()+5);
    btnShow->setText("开始检测特征脸");
    connect(btnShow,&QPushButton::clicked,[=](){
        showEgenFaceRecoginzer("");
    });

}

void Face_Eigen_Face_Recognizer::dropEvent(QDropEvent *event){
    path = event->mimeData()->urls().at(0).toLocalFile();
    showEgenFaceRecoginzer(path.toStdString().c_str());
}

void Face_Eigen_Face_Recognizer::showEgenFaceRecoginzer(const char * filePath){
    string filename = string("/Users/yangwei/Documents/tony/opencv/orl_faces/targetData.txt");
    ifstream file(filename,ifstream::in);
    string line,path,classLabel;//行、路径、标签
    vector<Mat> images;
    vector<int> labels;
    while(getline(file,line)){

        stringstream liness(line);
        getline(liness,path,' ');
        getline(liness,classLabel);
        //        if (!path.empty() && !labels.empty()) {
        cout << "path :"<< classLabel.c_str()<<endl;;
        images.push_back(imread(path, 0));
        labels.push_back(atoi(classLabel.c_str()));
        //        }
    }
    file.close();
    if (images.size() < 1 || labels.size() < 1) {
        qDebug()<<"invalid image path...\n";
        return;
    }

    int width = images[0].cols;
    int height = images[0].rows;
    //cout << "width:"<<width<<"|"<<"height:"<<height<<endl;
    ////准备测试数据和测试label
    //Mat testMatSample = images[images.size()-1];
    //int testLabel = labels[labels.size()-1];
    //imshow("testMatSample",testMatSample);
    //images.pop_back();
    //labels.pop_back();

    ////接下来就是最重要的步骤
    ////1.训练
    //Ptr<BasicFaceRecognizer> model = EigenFaceRecognizer::create();
    //model->train(images,labels);
    ////2.预测
    //int predictedLabel = model->predict(testMatSample);

    ////此处如果样本和预测结果是一致的就说明此次识别是算法是成功的
    //cout << "testLabel:"<<testLabel<<endl;
    //cout <<"predictedLabel:"<<predictedLabel<<endl;

    ////从训练结果中获取均值、特征向量、特征值矩阵
    //Mat eigenvalues = model->getEigenValues();
    //Mat eigenvectors = model->getEigenVectors();
    //Mat mean = model->getMean();
    ////得到均值脸
    //Mat meanFace = mean.reshape(1,height);
    //Mat dst;
    ////归一化0~255并输出
    //if(meanFace.channels()==1){//单通道图像
    //    normalize(meanFace,dst,0,255,NORM_MINMAX,CV_8UC1);
    //}else{//多通道图像
    //    normalize(meanFace,dst,0,255,NORM_MINMAX,CV_8UC3);
    //}
    //imshow("dist",dst);

//    //输出特征脸
//    for (int i = 0; i < min(16, eigenvectors.cols); i++) {
//        Mat ev = eigenvectors.col(i).clone();
//        Mat grayscale;
//        Mat eigenFace = ev.reshape(1, height);
//        if (eigenFace.channels() == 1) {
//            normalize(eigenFace, grayscale, 0, 255, NORM_MINMAX, CV_8UC1);
//        }
//        else if (eigenFace.channels() == 3) {
//            normalize(eigenFace, grayscale, 0, 255, NORM_MINMAX, CV_8UC3);
//        }
//        Mat colorface;
//        applyColorMap(grayscale, colorface, COLORMAP_BONE);
//        char* winTitle = new char[128];
//        sprintf(winTitle, "eigenface_%d", i);
//        imshow(winTitle, colorface);
//    }

//    for (int num = 0; num < min(eigenvectors.cols, 16); num++) {
//            Mat evs = eigenvectors.col(num);
//            Mat projection = LDA::subspaceProject(evs, mean, images[0].reshape(1, 1));
//            Mat reconstruction = LDA::subspaceReconstruct(evs, mean, projection);

//            Mat result = reconstruction.reshape(1, height);
//            if (result.channels() == 1) {
//                normalize(result, reconstruction, 0, 255, NORM_MINMAX, CV_8UC1);
//            }
//            else if (result.channels() == 3) {
//                normalize(result, reconstruction, 0, 255, NORM_MINMAX, CV_8UC3);
//            }
//            char* winTitle = new char[128];
//            sprintf(winTitle, "recon_face_%d", num);
//            imshow(winTitle, reconstruction);
//        }




}

/**
 * 准备人脸数据
 * 将人脸数据写入txt文件中
 * @brief Face_Eigen_Face_Recognizer::prepareImageData
 */
void Face_Eigen_Face_Recognizer::prepareImageData(const char * dirPath,char *appStr){
    //DIR *pDir;
    //struct dirent *ptr;
    //if(!(pDir=opendir(dirPath))){
    //    qDebug()<<"Folder doesn't Exist!";
    //    return;
    //}
    //while((ptr=readdir(pDir))!=0){
    //    if(strcmp(ptr->d_name,".")!=0&&strcmp(ptr->d_name,"..")!=0){
    //        char resultStr[100];
    //        sprintf(resultStr,"%s%s",dirPath,ptr->d_name);

    //        struct stat s;
    //        if(stat(resultStr,&s)==0){//路径存在
    //            if(s.st_mode&S_IFDIR){//文件夹
    //                char *dirName = ptr->d_name;
    //                char targetName[5];
    //                memcpy(targetName,dirName+1,strlen(dirName));
    //                cout <<"dirName:"<<dirName<< "--->targetName:"<<targetName<<endl;
    //                prepareImageData(resultStr,targetName);
    //            }
    //        }else{
    //            sprintf(resultStr,"%s/%s",dirPath,ptr->d_name);
    //            //                cout << resultStr<<endl;
    //            //                cout <<"error"<<endl;
    //            //将得到的数据存储到txt文件中
    //            if(out.is_open()){
    //                out << resultStr <<" "<<appStr<<endl;
    //            }else{
    //                cout <<"file is not opened"<<endl;
    //            }

    //        }

    //    }
    //}
    //closedir(pDir);
}
